package com.ymy.spring.cloud.sentinel.core.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.ymy.spring.cloud.sentinel.core.degrade.BlockExceptionHandler;
import com.ymy.spring.cloud.sentinel.core.degrade.FallbackHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import static com.ymy.spring.cloud.sentinel.core.config.SentinelConfig.*;

/**
 * {@link SentinelResource} 注解使用进行流控
 * 如何使用：
 * 1. 导包：sentinel-annotation-aspectj.
 * 2. 添加 Bean：SentinelResourceAspect.
 * 3. @SentinelResource 参数
 * - 3.1. value: 受保护的资源名.
 * - 3.2. blockHandler: 限流/降级后的处理方法.
 * - 3.3. fallback：业务出异常后的回调方法.
 *
 * @author Ringo
 * @date 2021/10/5 17:36
 */
@RestController
public class SentinelResourceAnnotationDemoController {


    // 流量控制
    // blockHandler 和 fallback 与方法在不同类中
    @GetMapping("/user/{id}")
    @SentinelResource(value = USER_RESOURCE_NAME,
            blockHandler = "getUser",
            fallback = "getUser",
            blockHandlerClass = BlockExceptionHandler.class,
            fallbackClass = FallbackHandler.class)
    public String getUser(@PathVariable("id") String id) {
        return "zsf =>" + id;
    }

    // ====================================================================================

    // 流量控制
    // blockHandler 和 fallback 与方法在同一个类中
    @SentinelResource(value = BOOK_RESOURCE_NAME,
            blockHandler = "blockExceptionHandler",
            fallback = "fallback")
    @GetMapping("/book")
    public String book() {
        return "西游记";
    }


    /**
     * 被流控后降级的方法
     */
    public String blockExceptionHandler(BlockException ex) {
        return "被流控了 cause:" + ex.getMessage();
    }

    /**
     * 业务异常的回调
     */
    public String fallback(Throwable t) {
        return "fallback cause:" + t.getMessage();
    }

    // ================================================================================================
    // 服务熔断降级 Service Degrade
    @GetMapping("/degrade")
    @SentinelResource(value = DEGRADE_RESOURCE_NAME,
            blockHandler = "degradeMethodBlockHandler",
            fallback = "degradeMethodFallBackHandler")
    public String degrade() {
        throw new RuntimeException("RuntimeException");
    }

    public String degradeMethodBlockHandler(BlockException ex) {
        return "服务熔断降级 cause: " + ex.getMessage();
    }

    public String degradeMethodFallBackHandler(Throwable t) {
        return "业务异常 cause:" + t.getMessage();
    }
}
